package cn.iocoder.yudao.module.eval.controller.admin.score;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.module.eval.controller.admin.score.vo.*;
import cn.iocoder.yudao.module.eval.dal.dataobject.score.EvalScoreRecordDO;
import cn.iocoder.yudao.module.eval.dal.dataobject.score.EvalScoreSummaryDO;
import cn.iocoder.yudao.module.eval.service.score.EvalScoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;

@Tag(name = "管理后台 - 评分与成绩管理")
@RestController
@RequestMapping("/eval/score")
@Validated
@Slf4j
public class EvalScoreController {

    @Resource
    private EvalScoreService scoreService;

    // ==================== 评分记录管理 ====================

    @PostMapping("/record")
    @Operation(summary = "提交评分记录")
    @PreAuthorize("@ss.hasPermission('eval:score:create')")
    @ApiAccessLog(operateType = CREATE)
    public CommonResult<Long> submitScoreRecord(@Valid @RequestBody EvalScoreRecordSaveReqVO saveReqVO) {
        return success(scoreService.submitScoreRecord(saveReqVO));
    }

    @PutMapping("/record/{recordId}")
    @Operation(summary = "更新评分记录")
    @Parameter(name = "recordId", description = "记录ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:update')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> updateScoreRecord(@PathVariable("recordId") Long recordId,
                                                   @Valid @RequestBody EvalScoreRecordSaveReqVO updateReqVO) {
        updateReqVO.setId(recordId);
        scoreService.updateScoreRecord(updateReqVO);
        return success(true);
    }

    @GetMapping("/record/plan/{planId}")
    @Operation(summary = "查询评分记录")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @Parameter(name = "candidateId", description = "参评人员ID", required = false)
    @Parameter(name = "evaluatorId", description = "考评员ID", required = false)
    @Parameter(name = "subjectId", description = "科目ID", required = false)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<List<EvalScoreRecordRespVO>> getScoreRecords(
            @PathVariable("planId") Long planId,
            @RequestParam(value = "candidateId", required = false) Long candidateId,
            @RequestParam(value = "evaluatorId", required = false) Long evaluatorId,
            @RequestParam(value = "subjectId", required = false) Long subjectId) {
        List<EvalScoreRecordDO> list = scoreService.getScoreRecords(planId, candidateId, evaluatorId, subjectId);
        return success(BeanUtils.toBean(list, EvalScoreRecordRespVO.class));
    }

    @GetMapping("/record/{recordId}")
    @Operation(summary = "获取评分记录详情")
    @Parameter(name = "recordId", description = "记录ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<EvalScoreRecordRespVO> getScoreRecord(@PathVariable("recordId") Long recordId) {
        EvalScoreRecordDO record = scoreService.getScoreRecord(recordId);
        return success(BeanUtils.toBean(record, EvalScoreRecordRespVO.class));
    }

    @PostMapping("/record/{recordId}/submit")
    @Operation(summary = "提交评分")
    @Parameter(name = "recordId", description = "记录ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:submit')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> submitScore(@PathVariable("recordId") Long recordId) {
        scoreService.submitScore(recordId);
        return success(true);
    }

    @PostMapping("/record/{recordId}/confirm")
    @Operation(summary = "确认评分")
    @Parameter(name = "recordId", description = "记录ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:confirm')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> confirmScore(@PathVariable("recordId") Long recordId) {
        scoreService.confirmScore(recordId);
        return success(true);
    }

    @PostMapping("/record/batch-submit")
    @Operation(summary = "批量提交评分")
    @PreAuthorize("@ss.hasPermission('eval:score:submit')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> batchSubmitScores(@Valid @RequestBody EvalScoreBatchSubmitReqVO batchSubmitReqVO) {
        scoreService.batchSubmitScores(batchSubmitReqVO.getRecordIds());
        return success(true);
    }

    @PostMapping("/record/batch-confirm")
    @Operation(summary = "批量确认评分")
    @PreAuthorize("@ss.hasPermission('eval:score:confirm')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> batchConfirmScores(@Valid @RequestBody EvalScoreBatchConfirmReqVO batchConfirmReqVO) {
        scoreService.batchConfirmScores(batchConfirmReqVO.getRecordIds());
        return success(true);
    }

    // ==================== 成绩计算与汇总 ====================

    @PostMapping("/calculate/plan/{planId}")
    @Operation(summary = "触发成绩计算")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:calculate')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> calculateScores(@PathVariable("planId") Long planId,
                                                 @Valid @RequestBody EvalScoreCalculationReqVO calculationReqVO) {
        scoreService.calculateScores(planId, calculationReqVO);
        return success(true);
    }

    @GetMapping("/summary/plan/{planId}")
    @Operation(summary = "查询成绩汇总")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @Parameter(name = "evaluationResult", description = "评价结果", required = false)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<PageResult<EvalScoreSummaryRespVO>> getScoreSummaries(
            @PathVariable("planId") Long planId,
            @RequestParam(value = "evaluationResult", required = false) String evaluationResult,
            @Valid EvalScoreSummaryPageReqVO pageReqVO) {
        pageReqVO.setPlanId(planId);
        pageReqVO.setEvaluationResult(evaluationResult);
        PageResult<EvalScoreSummaryDO> pageResult = scoreService.getScoreSummaryPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, EvalScoreSummaryRespVO.class));
    }

    @GetMapping("/summary/candidate/{candidateId}")
    @Operation(summary = "获取个人成绩详情")
    @Parameter(name = "candidateId", description = "参评人员ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<EvalScoreSummaryRespVO> getCandidateScoreSummary(@PathVariable("candidateId") Long candidateId) {
        EvalScoreSummaryDO summary = scoreService.getCandidateScoreSummary(candidateId);
        return success(BeanUtils.toBean(summary, EvalScoreSummaryRespVO.class));
    }

    @PostMapping("/summary/{summaryId}/review")
    @Operation(summary = "成绩复核")
    @Parameter(name = "summaryId", description = "成绩汇总ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:review')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> reviewScore(@PathVariable("summaryId") Long summaryId,
                                            @Valid @RequestBody EvalScoreReviewReqVO reviewReqVO) {
        scoreService.reviewScore(summaryId, reviewReqVO);
        return success(true);
    }

    @GetMapping("/summary/plan/{planId}/export")
    @Operation(summary = "导出成绩单")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @Parameter(name = "format", description = "导出格式", required = false, example = "excel")
    @PreAuthorize("@ss.hasPermission('eval:score:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportScoreSummary(@PathVariable("planId") Long planId,
                                  @RequestParam(value = "format", defaultValue = "excel") String format,
                                  HttpServletResponse response) throws IOException {
        List<EvalScoreSummaryDO> list = scoreService.getScoreSummariesByPlan(planId);
        // 导出 Excel
        ExcelUtils.write(response, "成绩单.xls", "成绩", EvalScoreSummaryRespVO.class,
                BeanUtils.toBean(list, EvalScoreSummaryRespVO.class));
    }

    // ==================== 成绩统计分析 ====================

    @GetMapping("/statistics/plan/{planId}")
    @Operation(summary = "成绩统计概览")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<EvalScoreStatisticsRespVO> getScoreStatistics(@PathVariable("planId") Long planId) {
        EvalScoreStatisticsRespVO statistics = scoreService.getScoreStatistics(planId);
        return success(statistics);
    }

    @GetMapping("/statistics/plan/{planId}/distribution")
    @Operation(summary = "成绩分布统计")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<EvalScoreDistributionRespVO> getScoreDistribution(@PathVariable("planId") Long planId) {
        EvalScoreDistributionRespVO distribution = scoreService.getScoreDistribution(planId);
        return success(distribution);
    }

    @GetMapping("/statistics/plan/{planId}/subject")
    @Operation(summary = "科目成绩统计")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<List<EvalSubjectScoreStatisticsRespVO>> getSubjectScoreStatistics(@PathVariable("planId") Long planId) {
        List<EvalSubjectScoreStatisticsRespVO> statistics = scoreService.getSubjectScoreStatistics(planId);
        return success(statistics);
    }

    @GetMapping("/statistics/evaluator/{evaluatorId}")
    @Operation(summary = "考评员评分统计")
    @Parameter(name = "evaluatorId", description = "考评员ID", required = true)
    @Parameter(name = "startDate", description = "开始日期", required = false)
    @Parameter(name = "endDate", description = "结束日期", required = false)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<EvalEvaluatorScoreStatisticsRespVO> getEvaluatorScoreStatistics(
            @PathVariable("evaluatorId") Long evaluatorId,
            @RequestParam(value = "startDate", required = false) String startDate,
            @RequestParam(value = "endDate", required = false) String endDate) {
        EvalEvaluatorScoreStatisticsRespVO statistics = scoreService.getEvaluatorScoreStatistics(evaluatorId, startDate, endDate);
        return success(statistics);
    }

    // ==================== 成绩查询与验证 ====================

    @GetMapping("/query/candidate")
    @Operation(summary = "参评人员成绩查询")
    @Parameter(name = "idNumber", description = "身份证号", required = false)
    @Parameter(name = "name", description = "姓名", required = false)
    @Parameter(name = "planId", description = "计划ID", required = false)
    @PreAuthorize("@ss.hasPermission('eval:score:query')")
    public CommonResult<List<EvalScoreSummaryRespVO>> queryCandidateScores(
            @RequestParam(value = "idNumber", required = false) String idNumber,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "planId", required = false) Long planId) {
        List<EvalScoreSummaryDO> list = scoreService.queryCandidateScores(idNumber, name, planId);
        return success(BeanUtils.toBean(list, EvalScoreSummaryRespVO.class));
    }

    @GetMapping("/verify/{summaryId}")
    @Operation(summary = "验证成绩真伪")
    @Parameter(name = "summaryId", description = "成绩汇总ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:verify')")
    public CommonResult<EvalScoreVerificationRespVO> verifyScore(@PathVariable("summaryId") Long summaryId) {
        EvalScoreVerificationRespVO verification = scoreService.verifyScore(summaryId);
        return success(verification);
    }

    // ==================== 我的评分任务 ====================

    @GetMapping("/my-tasks")
    @Operation(summary = "我的评分任务")
    @Parameter(name = "status", description = "任务状态", required = false)
    @PreAuthorize("@ss.hasPermission('eval:score:my-tasks')")
    public CommonResult<List<EvalScoreTaskRespVO>> getMyScoreTasks(
            @RequestParam(value = "status", required = false) Integer status) {
        List<EvalScoreTaskRespVO> tasks = scoreService.getMyScoreTasks(status);
        return success(tasks);
    }

    @GetMapping("/my-tasks/plan/{planId}")
    @Operation(summary = "我在指定计划的评分任务")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:score:my-tasks')")
    public CommonResult<List<EvalScoreTaskRespVO>> getMyScoreTasksByPlan(@PathVariable("planId") Long planId) {
        List<EvalScoreTaskRespVO> tasks = scoreService.getMyScoreTasksByPlan(planId);
        return success(tasks);
    }

    @GetMapping("/my-progress")
    @Operation(summary = "我的评分进度")
    @PreAuthorize("@ss.hasPermission('eval:score:my-tasks')")
    public CommonResult<EvalMyScoreProgressRespVO> getMyScoreProgress() {
        EvalMyScoreProgressRespVO progress = scoreService.getMyScoreProgress();
        return success(progress);
    }

}
